package org.fyp.synchrona.xml.impl;




import java.io.File;
import java.io.StringReader;
import java.util.LinkedList;
import java.util.List;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.stream.events.XMLEvent;

import org.fyp.synchrona.core.impl.RSADecrypter;
import org.fyp.synchrona.core.info.impl.Account;
import org.fyp.synchrona.core.info.impl.DMMLData;
import org.fyp.synchrona.util.DataQueue;
import org.fyp.synchrona.util.IAccount;
import org.fyp.synchrona.util.IDMMLData;
import org.fyp.synchrona.util.ITask;
import org.fyp.synchrona.util.Task;

import com.ctc.wstx.stax.WstxInputFactory;
import org.codehaus.stax2.XMLInputFactory2;




public class DMMLParser {
	
	private WstxInputFactory xmlInputFactory = null;
	private XMLStreamReader xmlStreamReader = null;
	private XMLStreamWriter xmlStreamWriter = null;

	private IAccount account = null;
	private ITask task;
	
	
	private static DMMLParser dmml;
	
	private DMMLParser(){
		
	}
	
	public static synchronized DMMLParser getDMMLParser(){
		
		if(dmml == null){
			
			dmml = new DMMLParser();
			return dmml;
			
		}else{

			return dmml;
			
		}
		
	}
	
	
	public IDMMLData parseXML(String dmml) throws XMLStreamException{
		xmlInputFactory = new WstxInputFactory();
		xmlInputFactory.setProperty(XMLInputFactory2.IS_REPLACING_ENTITY_REFERENCES, Boolean.FALSE);
		xmlInputFactory.setProperty(XMLInputFactory2.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
		xmlInputFactory.setProperty(XMLInputFactory2.IS_COALESCING,Boolean.FALSE);
		xmlInputFactory.setProperty(XMLInputFactory2.IS_VALIDATING,Boolean.FALSE);
		xmlInputFactory.configureForSpeed();
		
		/**
		 * contains the parsed output. update data is stored in tasks object
		 * account data is stored in account object
		 * both update and account data is stored in dmmlData object. 
		 * */
		
		IDMMLData dmmlData = new DMMLData();
		List<ITask> tasks = new LinkedList<ITask>();
		List<IAccount> accounts = new LinkedList<IAccount>();
		
		
		
		String Tag = "";
		String attributeContent = "";
		
		
		/**
		 * start reading from the xml
		 * this is for testing purpose :: xmlStreamReader = xmlInputFactory.createXMLStreamReader(new StringReader(dmml));
		 **/
		
		xmlStreamReader = xmlInputFactory.createXMLStreamReader(new StringReader(dmml));
		
		/**
		 * reading start of document tag
		 **/
		
		int eventType = xmlStreamReader.getEventType();
		
		
		/**
		 * This reads the UPDATE tag which is the first tag in the web service
		 **/
		
		eventType = xmlStreamReader.next();
		Tag = xmlStreamReader.getName().toString();
		
		if(Tag.equals("UPDATE")){
			while(xmlStreamReader.hasNext()){
				eventType = xmlStreamReader.next();
				switch(eventType){
				
				case XMLEvent.START_ELEMENT:
					if(xmlStreamReader.getName().toString()=="SERVICE"){
						System.out.println("########################NEW ACCOUNT OBJECT IS CREATING#########################");
						System.out.println("\n");
						account = new Account();
						eventType = xmlStreamReader.next();
						eventType = xmlStreamReader.next();
						System.out.println(eventType);
						String attributeTag = xmlStreamReader.getAttributeValue("","elementName");
						attributeContent = xmlStreamReader.getElementText();
						System.out.println("*servicename*");
						account.setServiceName(attributeContent);
						System.out.println(account.getServiceName());
						
						eventType = xmlStreamReader.next();
						eventType = xmlStreamReader.next();
						attributeTag = xmlStreamReader.getAttributeValue("","elementName");
						attributeContent = xmlStreamReader.getElementText();
						System.out.println("*service crdential username tag*");
						System.out.println(attributeTag);
						System.out.println("*service crdential username content*");
						account.setUserName(attributeContent);
						System.out.println(account.getUserName());
						
						eventType = xmlStreamReader.next();
						eventType = xmlStreamReader.next();
						attributeTag = xmlStreamReader.getAttributeValue("","elementName");
						attributeContent = xmlStreamReader.getElementText();
						System.out.println("*service crdential password tag*");
						System.out.println(attributeTag);
						System.out.println("*service crdential password content*");
						account.setPassword(RSADecrypter.decryptPassword(attributeContent));
						System.out.println(account.getPassword());
						
						accounts.add(account);
						System.out.println("\n");
						System.out.println("------------------------ACCOUNT OBJECT CREATION FINISHED-----------------------------");
						System.out.println("\n");
					}else if(xmlStreamReader.getName().toString()=="Element"){
						
						String attributeTag = xmlStreamReader.getAttributeValue("","elementName");
						attributeContent = xmlStreamReader.getElementText();
						task = new Task();
						task.setAttributeName(attributeTag);
						task.setAttributeValue(attributeContent);
						System.out.println("\n");
						System.out.println("+++++++++update data attribute tag++++++++++++++++++++++");
						System.out.println(task.getAttributeName());
						System.out.println("*********update data attribute tag content**************");
						System.out.println("\n");
					    System.out.println(task.getAttributeValue());
					    
					    /**
					     * set the service type
					     */
					    
				    	if(task.getAttributeValue().contains("blogger.com")){
					    	dmmlData.setServiceName("www.blogger.com");
					    }else if(task.getAttributeValue().contains("twitter.com")){
					    	dmmlData.setServiceName("www.twitter.com");
					    }else if(task.getAttributeValue().contains("facebook.com")){
					    	dmmlData.setServiceName("www.facebook.com");
					    }else if(task.getAttributeValue().contains("editadvanced.php")){
					    	dmmlData.setServiceName("www.moodle.com");
					    }					    	
					   
					    
					    
	     				tasks.add(task);
					}
					
					/**
					 * setting the update type
					 * */
					
					if(xmlStreamReader.getName().toString()=="PROFILE"){
						dmmlData.setUpdateType("PROFILE");
					}else if(xmlStreamReader.getName().toString()=="STS"){
						dmmlData.setUpdateType("STS");
					}
					
				}
			}
			dmmlData.setAccount(accounts);
			dmmlData.setTask(tasks);
			return dmmlData;//tasks
		}else{
			return null;
		}
	}

}
